package com.study.tiandimapview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.AttributeSet;
import android.webkit.JavascriptInterface;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageButton;

import androidx.annotation.RequiresApi;
import androidx.arch.core.util.Function;

import com.blankj.utilcode.util.ToastUtils;
import com.study.tiandimapview.R.mipmap;
import com.egis.core.EGISObject;
import com.egis.core.mbtile.MbtileUtils;
import com.egis.core.mbtile.OfflineDataUtils;
import com.egis.core.mbtile.bean.MbtileBean;
import com.egis.display.element.Element;
import com.egis.gdm.CommandManager;
import com.egis.gdm.CommandNotify;
import com.egis.gdm.Container;
import com.egis.geom.Point;
import com.egis.layer.ElementLayer;
import com.egis.layer.GraphicSelectionSet;
import com.egis.map.CoordinateTransform;
import com.egis.map.MeasureService;
import com.egis.map.scalecontrol.ScaleControlOption;
import com.egis.symbol.PictureMarkerSymbol;
import com.egis.symbol.SymbolTable;
import com.egis.utils.DensityUtils;
import com.egis.utils.LocationUtils;
import com.egis.widget.TooltipWare;
import com.yanzhenjie.permission.Action;
import com.yanzhenjie.permission.AndPermission;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.List;

import wendu.dsbridge.DWebView;

public class MapView extends DWebView {
    public static final String ICON_LOCATION = "";
    private Context mContext;
    private MapView.IInitCompleteCallback callback;
    private static final long MIN_TIME = 100L;
    private static final long MIN_DISTANCE = 0L;
    private ImageButton mBtnZoomIn;
    private ImageButton mBtnZoomOut;
    private ImageButton mBtnLocate;
    private com.egis.map.Map map;
    private CommandManager manager;
    private Container container;
    private CommandNotify notify;
    private TooltipWare tooltipWare;
    private MeasureService measureService;
    private CoordinateTransform coordinateTransform;
    private static String defaultSaveRootPath = Environment.getDownloadCacheDirectory().getAbsolutePath();
    java.util.Map<String, MbtileBean> mOfflineBounds = new HashMap();
    private int defaultLevel = 10;
    private Point defaultCenter = new Point(116.3466D, 39.8704D);
    private int maxZoom = 18;
    private int minZoom = 2;
    private double minX = -180.0D;
    private double minY = -90.0D;
    private double maxX = 180.0D;
    private double maxY = 90.0D;
    private boolean isShowScaleControl;
    private ScaleControlOption scaleControlOption;

    public MapView(Context context) {
        super(context);
        this.mContext = context;
        this.initViews(context);
        EGISObject.setdWebView(this);
        this.addJavascriptObject(new MapView.MapViewLoadComplete(), "mapview");
        this.getSettings().setJavaScriptEnabled(true);
        this.setWebViewClient(new MapView.MapViewClient());
        this.init();
    }

    public MapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
        this.initViews(context);
        EGISObject.setdWebView(this);
        this.addJavascriptObject(new MapView.MapViewLoadComplete(), "mapview");
        this.getSettings().setJavaScriptEnabled(true);
        this.setWebViewClient(new MapView.MapViewClient());
        this.init();
    }

    public void setDefaultParams(MapParams params) {
        if (params != null) {
            this.defaultLevel = params.getDefaultLevel();
            this.defaultCenter = params.getDefaultCenter();
            this.maxZoom = params.getMaxZoom();
            this.minZoom = params.getMinZoom();
            this.minX = params.getMinX();
            this.minY = params.getMinY();
            this.maxX = params.getMaxX();
            this.maxY = params.getMaxY();
            this.isShowScaleControl = params.isShowScaleControl();
            this.scaleControlOption = params.getScaleControlOption();
        }
    }

    public void onCreate() {
    }

    public void onDestroy() {
        if (this.map != null) {
            this.map.onDestroy();
        }

        EGISObject.removeWebView(this);
    }

    public void onResume() {
        super.onResume();
        EGISObject.setdWebView(this);
    }

    private void initMap() {
        this.map = new com.egis.map.Map(this.defaultLevel, this.defaultCenter, this.maxZoom, this.minZoom, this.minX, this.minY, this.maxX, this.maxY);
        if (this.isShowScaleControl) {
            if (this.scaleControlOption == null) {
                this.map.addScaleControl(new ScaleControlOption());
            } else {
                this.map.addScaleControl(this.scaleControlOption);
            }
        }

        this.map.init("egismap");
        GraphicSelectionSet graphicSelectionSet = new GraphicSelectionSet();
        new SymbolTable();
        this.tooltipWare = new TooltipWare(this.map);
        this.manager = new CommandManager();
        this.measureService = new MeasureService();
        this.coordinateTransform = new CoordinateTransform();
        this.notify = new CommandNotify(this.manager);
        this.container = new Container();
        this.container.regist("map", this.map);
        this.container.regist("graphicSelectionSet", graphicSelectionSet);
        this.container.regist("commandNotify", this.notify);
        this.container.regist("tooltipWare", this.tooltipWare);
        ElementLayer layer = new ElementLayer("location_element", "location_element", 40);
        layer.setzIndex(999);
        this.map.addLayer(layer);
        if (this.callback != null) {
            this.callback.complete();
        }

    }

    public void setCompleteCallback(MapView.IInitCompleteCallback callback) {
        this.callback = callback;
    }

    private void init() {
        this.scanOfflineMap(defaultSaveRootPath);
        this.loadUrl("file:///android_asset/index.html");
    }

    public com.egis.map.Map getMap() {
        return this.map;
    }

    public CommandManager getCommandManager() {
        return this.manager;
    }

    public Container getContainer() {
        return this.container;
    }

    public MeasureService getMeasureService() {
        return this.measureService;
    }

    public TooltipWare getTooltipWare() {
        return this.tooltipWare;
    }

    public CoordinateTransform getCoordinateTransform() {
        return this.coordinateTransform;
    }

    public CommandNotify getNotify() {
        return this.notify;
    }

    private void initViews(Context context) {
        this.mBtnZoomIn = new ImageButton(this.getContext());
        this.mBtnZoomIn.setImageResource(mipmap.icon_zoom_in);
        this.mBtnZoomIn.setBackgroundColor(-1);
        this.mBtnZoomOut = new ImageButton(this.getContext());
        this.mBtnZoomOut.setImageResource(mipmap.icon_zoom_out);
        this.mBtnZoomOut.setBackgroundColor(-1);
        this.mBtnLocate = new ImageButton(this.getContext());
        this.mBtnLocate.setImageResource(mipmap.icon_locate);
        this.mBtnLocate.setBackgroundColor(-1);
        this.addView(this.mBtnZoomIn);
        this.addView(this.mBtnZoomOut);
        this.addView(this.mBtnLocate);
        this.post(() -> {
            int size = DensityUtils.dip2px(this.getContext(), 32.0F);
            int x = DensityUtils.dip2px(this.getContext(), 12.0F);
            int margin = DensityUtils.dip2px(this.getContext(), 6.0F);
            int marginBottom = DensityUtils.dip2px(this.getContext(), 24.0F);
            LayoutParams lpZoomIn = new LayoutParams(size, size, x, this.getHeight() - 3 * size - margin - marginBottom);
            this.mBtnZoomIn.setLayoutParams(lpZoomIn);
            LayoutParams lpZoomOut = new LayoutParams(size, size, x, this.getHeight() - 2 * size - margin - marginBottom);
            this.mBtnZoomOut.setLayoutParams(lpZoomOut);
            LayoutParams lpLocate = new LayoutParams(size, size, x, this.getHeight() - size - marginBottom);
            this.mBtnLocate.setLayoutParams(lpLocate);
        });
        this.mBtnZoomIn.setOnClickListener((v) -> {
            this.map.zoomIn();
        });
        this.mBtnZoomOut.setOnClickListener((v) -> {
            this.map.zoomOut();
        });
        this.mBtnLocate.setOnClickListener((v) -> {
            AndPermission.with(this.mContext).runtime().permission(new String[]{"android.permission.ACCESS_FINE_LOCATION"}).onDenied(new Action<List<String>>() {
                public void onAction(List<String> data) {
                    ToastUtils.showShort("定位权限申请失败，定位功能无法使用");
                }
            }).onGranted(new Action<List<String>>() {
                public void onAction(List<String> data) {
                    try {
                        com.egis.map.Map map = MapView.this.getMap();
                        MapView.this.location((position) -> {
                            Point point = new Point(position.getLongitude(), position.getLatitude(), 0.0D);
                            map.setCenter(point);
                            MapView.this.drawLocation(position);
                            return null;
                        });
                    } catch (Exception var3) {
                        ToastUtils.showShort("定位失败！");
                    }

                }
            }).start();
        });
    }

    @SuppressLint({"MissingPermission"})
    private void location(final Function<Location, Void> callBack) {
        if (LocationUtils.isGpsEnabled()) {
            LocationUtils.register(100L, 0L, new LocationUtils.OnLocationChangeListener() {
                @RequiresApi(
                        api = 24
                )
                public void getLastKnownLocation(Location location) {
                    callBack.apply(location);
                }

                @RequiresApi(
                        api = 24
                )
                public void onLocationChanged(Location location) {
                    callBack.apply(location);
                    LocationUtils.unregister();
                }

                public void onStatusChanged(String provider, int status, Bundle extras) {
                }
            });
        } else {
            LocationUtils.openGpsSettings();
        }

    }

    @SuppressLint("WrongConstant")
    public void setZoomShow(boolean isShow) {
        if (isShow) {
            this.mBtnZoomIn.setVisibility(0);
            this.mBtnZoomOut.setVisibility(0);
        } else {
            this.mBtnZoomIn.setVisibility(8);
            this.mBtnZoomOut.setVisibility(8);
        }

    }

    @SuppressLint("WrongConstant")
    public void setLocationShow(boolean isShow) {
        if (isShow) {
            this.mBtnLocate.setVisibility(0);
        } else {
            this.mBtnLocate.setVisibility(8);
        }

    }

    public void scanOfflineMap(String path) {
        defaultSaveRootPath = path;
        (new MapView.ScanTask()).execute(new String[]{path});
    }

    void drawLocation(Location position) {
        ElementLayer layer = (ElementLayer) this.map.findLayer("location_element");
        layer.setzIndex(99999);
        Point point = new Point(position.getLongitude(), position.getLatitude(), 0.0D);
        point.setSrid(4490);
        PictureMarkerSymbol pictureMarkerSymbol = new PictureMarkerSymbol();
        pictureMarkerSymbol.setWidth(48);
        pictureMarkerSymbol.setHeight(48);
        pictureMarkerSymbol.setRotation((double) position.getBearing());
        pictureMarkerSymbol.setSource("");
        Element element = new Element();
        element.setGeometry(point);
        element.setSymbol(pictureMarkerSymbol);
        layer.add(element);
    }

    public void onPause() {
        super.onPause();
    }

    private class ScanTask extends AsyncTask<String, Integer, String> {
        private ScanTask() {
        }

        protected String doInBackground(String... params) {
            MapView.this.mOfflineBounds = MbtileUtils.scanFileSystem(params[0]);
            return null;
        }
    }

    private class MapViewLoadComplete {
        private MapViewLoadComplete() {
        }

        @JavascriptInterface
        public void initMapview(Object args) {
            MapView.this.post(new Runnable() {
                public void run() {
                    MapView.this.initMap();
                }
            });
        }
    }

    class MapViewClient extends WebViewClient {
        static final String KEY_TYPEFACE = "SimHei%20Regular";
        static final String KEY_PBF = ".pbf";
        static final String KEY_PNG = ".png";
        static final String KEY_JSON = ".json";

        MapViewClient() {
        }

        @RequiresApi(
                api = 21
        )
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            if (MapView.this.mOfflineBounds != null) {
                WebResourceResponse[] response = new WebResourceResponse[]{null};
                String url = request.getUrl().toString();
                if (url.toLowerCase().endsWith(".pbf")) {
                    byte[] tileData = MbtileUtils.getTileData(url, MapView.this.mOfflineBounds);
                    if (tileData == null) {
                        return super.shouldInterceptRequest(view, request);
                    } else {
                        response[0] = new WebResourceResponse("application/x-protobuf", "UTF-8", new ByteArrayInputStream(tileData));
                        return response[0];
                    }
                } else {
                    FileInputStream ins;
                    if (url.toLowerCase().endsWith(".png")) {
                        ins = OfflineDataUtils.getLocalFile(url, MapView.defaultSaveRootPath);
                        if (ins == null) {
                            return super.shouldInterceptRequest(view, request);
                        } else {
                            response[0] = new WebResourceResponse("image/*", "UTF-8", ins);
                            return response[0];
                        }
                    } else if (url.toLowerCase().endsWith(".json")) {
                        ins = OfflineDataUtils.getLocalFile(url, MapView.defaultSaveRootPath);
                        if (ins == null) {
                            return super.shouldInterceptRequest(view, request);
                        } else {
                            response[0] = new WebResourceResponse("application/json", "UTF-8", ins);
                            return response[0];
                        }
                    } else if (url.contains("SimHei%20Regular")) {
                        ins = OfflineDataUtils.getLocalTypeface(url, MapView.defaultSaveRootPath);
                        if (ins == null) {
                            return super.shouldInterceptRequest(view, request);
                        } else {
                            response[0] = new WebResourceResponse("application/x-protobuf", "UTF-8", ins);
                            return response[0];
                        }
                    } else {
                        ins = OfflineDataUtils.getLocalFile(url + ".json", MapView.defaultSaveRootPath);
                        if (ins == null) {
                            return super.shouldInterceptRequest(view, request);
                        } else {
                            response[0] = new WebResourceResponse("application/json", "UTF-8", ins);
                            return response[0];
                        }
                    }
                }
            } else {
                return super.shouldInterceptRequest(view, request);
            }
        }
    }

    public interface IInitCompleteCallback {
        void complete();
    }
}
